<template>
  <div class="chat-container">
    <!-- 消息列表 -->
    <div class="message-list" ref="messageListRef">
      <TransitionGroup name="message-fade">
        <div v-for="(msg, index) in messages" :key="index" class="message-wrapper">
          <div
            :class="[
              'message-bubble',
              { 'user-message': msg.isUser },
              { 'ai-message': !msg.isUser }
            ]"
          >
            <span v-if="msg.isUser || msg.content !== ''" v-html="marked(msg.content)"></span>
            <span v-else class="typing-indicator">
              <span></span><span></span><span></span>
            </span>
          </div>
        </div>
      </TransitionGroup>
    </div>

    <!-- 输入区域 -->
    <div class="input-area">
      <input
        v-model="inputMessage"
        @keyup.enter="sendMessage"
        placeholder="输入消息..."
        class="message-input"
        autofocus
      />
      <button @click="sendMessage" class="send-button">发送</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { streamModelApi } from '#/api/object/model' // 替换为你自己的 API
import { ref, nextTick, onMounted } from 'vue'
import { marked } from 'marked'

// 消息类型定义
interface Message {
  content: string
  isUser: boolean
  role: string
}

const messages = ref<Message[]>([])
const inputMessage = ref('')
const messageListRef = ref<HTMLElement | null>(null)
const isScrolling = ref(false)

// 发送消息
const sendMessage = async () => {
  const text = inputMessage.value.trim()
  if (!text) return

  messages.value.push({ content: text, isUser: true, role: 'user' })
  inputMessage.value = ''
  scrollToBottom()
  // 添加 AI 回复占位符
  messages.value.push({ content: '', isUser: false, role: 'assistant' })

  let messageStr = ''
  for await (const chunk of streamModelApi(messages.value)) {
    messageStr += chunk
    messages.value.splice(messages.value.length - 1, 1, {
      content: messageStr,
      isUser: false,
      role: 'assistant'
    })
      scrollToBottom()
  }

  localStorage.setItem('chat_list', JSON.stringify(messages.value))
}

// 平滑滚动到底部
const scrollToBottom = () => {
  if (isScrolling.value) return
  isScrolling.value = true

  requestAnimationFrame(() => {
    nextTick(() => {
      const messageListEl = messageListRef.value
      if (messageListEl) {
        messageListEl.scrollTop = messageListEl.scrollHeight
      }
      isScrolling.value = false
    })
  })
}

onMounted(() => {
  const dataListStr = localStorage.getItem('chat_list')
  if (dataListStr) {
    messages.value = JSON.parse(dataListStr)
    scrollToBottom()
  }

  const inputEl = document.querySelector('.message-input') as HTMLInputElement
  if (inputEl) {
    inputEl.addEventListener('focus', () => {
      setTimeout(() => window.scrollTo(0, document.body.scrollHeight), 300)
    })
  }
})
</script>

<style scoped>
.chat-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 80%;
  height: 90vh;
  margin: 0 auto;
  border: 1px solid #ccc;
  border-radius: 16px;
  overflow: hidden;
  background-color: #f2f2f7;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
    'Helvetica Neue', sans-serif;
}

.message-list {
  flex: 1;
  overflow-y: auto;
  background-color: #ffffff;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  position: relative;
}

.input-area {
  position: relative;
  display: flex;
  padding: 12px 20px;
  width: 100%;
  align-items: center;
  background-color: #ffffff;
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
}

.message-input {
  flex: 1;
  padding: 10px 14px;
  border-radius: 20px;
  border: 1px solid #ccc;
  outline: none;
  font-size: 16px;
  background-color: #fff;
  transition: border-color 0.3s ease;
}

.message-input:focus {
  border-color: #007aff;
}

.send-button {
  margin-left: 10px;
  padding: 10px 20px;
  background-color: #007aff;
  color: white;
  border: none;
  border-radius: 20px;
  font-size: 16px;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.send-button:hover {
  background-color: #005edc;
}

.message-wrapper {
  display: flex;
  flex-direction: column;
  padding: 8px 16px;
}

.message-bubble {
  max-width: 70%;
  padding: 14px 18px;
  border-radius: 24px;
  font-size: 16px;
  line-height: 1.5;
  word-wrap: break-word;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
  transition: all 0.2s ease-in-out;
}

.message-bubble:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}

.user-message {
  align-self: flex-end;
  background-color: #007aff;
  color: white;
  border-bottom-right-radius: 8px;
}

.ai-message {
  align-self: flex-start;
  background-color: #efeff4;
  color: #333;
  border-bottom-left-radius: 8px;
}

/* Typing 动画 */
.typing-indicator {
  display: inline-block;
  width: 40px;
  height: 16px;
  text-align: left;
}

.typing-indicator span {
  display: inline-block;
  width: 6px;
  height: 6px;
  margin: 2px;
  background-color: #888;
  border-radius: 50%;
  animation: typing-dots 1.4s infinite ease-in-out both;
}

.typing-indicator span:nth-child(1) {
  animation-delay: -0.32s;
}
.typing-indicator span:nth-child(2) {
  animation-delay: -0.16s;
}
.typing-indicator span:nth-child(3) {
  animation-delay: 0s;
}

@keyframes typing-dots {
  0%,
  80%,
  100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}

/* 淡入动画 */
.message-fade-enter-active,
.message-fade-leave-active {
  transition: all 0.3s ease;
  opacity: 0;
  transform: translateY(20px) scale(0.95);
}

.message-fade-enter-from,
.message-fade-leave-to {
  opacity: 0;
  transform: translateY(20px) scale(0.95);
}
</style>
